package com.example.tool.window;

import com.example.tool.db.SqlExec;
import com.example.tool.db.SqlExecute;
import com.example.tool.entity.ConfigDBEntity;
import com.example.tool.entity.ConfigEntity;
import com.example.tool.entity.FormDesign;
import com.example.tool.entity.SqlEntity;
import com.example.tool.entity.WindowEntity;
import com.example.tool.module.ModuleInformation;
import com.example.tool.module.ModuleInputEnum;
import com.example.tool.ui.HToolViewItem;
import com.example.tool.ui.SwingUi;
import com.example.tool.ui.SwingViewWrapper;
import com.example.tool.utils.ActionToolUtil;
import com.example.tool.utils.FileUtil;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiManager;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.content.ContentManager;
import com.intellij.ui.table.JBTable;
import org.jetbrains.annotations.NotNull;

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HToolWindowFactory implements ToolWindowFactory, DumbAware {
  private static final Logger LOG = Logger.getInstance(HToolWindowFactory.class);
  public static final Map<Project, WindowEntity> windowEntityMap = new HashMap<>();

  @Override
  public void init(@NotNull ToolWindow toolWindow) {
    toolWindow.setStripeTitle(ModuleInformation.MODULE_NAME);
    Project project = toolWindow.getProject();
    // 添加按钮
    List<DumbAwareAction> list = new ArrayList<>();
    RefreshAction refreshAction = getRefreshAction(project);
    list.add(refreshAction);
    list.add(new HToolWindowConfigAction());
    toolWindow.setTitleActions(list);
    ToolWindowFactory.super.init(toolWindow);
  }

  @Override
  public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
    try {
      ConfigDBEntity configDBEntity = ActionToolUtil.getInformationDB(project);
      if (configDBEntity == null) {
        ActionToolUtil.noConfigDB(project);
      }
    } catch (Exception e) {
      LOG.info(e.getMessage(), e);
    }
    // 表单表格
    List<String> columnsOne = new ArrayList<>();
    columnsOne.add("表单ID");
    columnsOne.add("表单名称");
    columnsOne.add("表单类型");
    List<List<Object>> getTableOneData;
    try {
      getTableOneData = getTableOneData(project);
    } catch (Exception e) {
      getTableOneData = new ArrayList<>();
    }
    JBTable jbTableOne = HToolWindowPage.crateTable(columnsOne, getTableOneData);
    // 中间过渡表
    HToolWindowPage hToolWindowPageOne = new HToolWindowPage(jbTableOne, "筛选表格：");
    JPanel jPanelOne = hToolWindowPageOne.getjPanel();
    String[] optionsHas = {"选定字段", "所有字段", "排除无关字段"};
    ComboBox<String> comboBoxHas = new ComboBox<>(optionsHas);
    String[] optionsShift = {"字段名称转拼音", "数据库名称"};
    ComboBox<String> comboBoxShift = new ComboBox<>(optionsShift);
    String[] optionsXml = {"是", "否"};
    ComboBox<String> comboBoxXml = new ComboBox<>(optionsXml);
    List<HToolViewItem<?>> hToolViewItems = new ArrayList<>();
    hToolViewItems.add(new HToolViewItem<>(ModuleInputEnum.FIELD_HAS, comboBoxHas));
    hToolViewItems.add(new HToolViewItem<>(ModuleInputEnum.FIELD_SHIFT, comboBoxShift));
    hToolViewItems.add(new HToolViewItem<>(ModuleInputEnum.FIELD_XML, comboBoxXml));
    SwingViewWrapper swingViewWrapper = new SwingViewWrapper(project, ModuleInformation.CONFIG_INFO, ModuleInformation.TIP_FORM, hToolViewItems);
    JComponent build = swingViewWrapper.build();
    // 字段表格
    List<String> columnsTwo = new ArrayList<>();
    columnsTwo.add("字段ID");
    columnsTwo.add("数据库字段");
    columnsTwo.add("字段名称");
    columnsTwo.add("字段类型");
    columnsTwo.add("数据类型");
    columnsTwo.add("表单名称");
    columnsTwo.add("数据库表");
    JBTable jbTableTwo = HToolWindowPage.crateTable(columnsTwo, new ArrayList<>());
    HToolWindowPage hToolWindowPageTwo = new HToolWindowPage(jbTableTwo, "筛选字段：");
    JPanel jPanelTwo = hToolWindowPageTwo.getjPanel();
    List<JPanel> jPanels = new ArrayList<>();
    jPanels.add(jPanelOne);
    jPanels.add((JPanel) build);
    jPanels.add(jPanelTwo);
    WindowEntity windowEntity = new WindowEntity(swingViewWrapper, hToolWindowPageOne, hToolWindowPageTwo, jPanels);
    windowEntityMap.put(project, windowEntity);
    JPanel jPanel = crateJPanel(project, toolWindow);
    ContentFactory contentFactory = ContentFactory.getInstance();
    Content content = contentFactory.createContent(jPanel, "", false);
    ContentManager contentManager = toolWindow.getContentManager();
    contentManager.addContent(content);
  }

  /**
   * 刷新按钮初始化
   * @param project 项目对象
   */
  @NotNull
  private RefreshAction getRefreshAction(Project project) {
    RefreshAction refreshAction = new RefreshAction();
    // 表单表格刷新按钮执行操作
    refreshAction.initRefresh(0, () -> {
      WindowEntity windowEntity = windowEntityMap.get(project);
      HToolWindowPage hToolWindowPageOne = windowEntity.getHToolWindowPageOne();
      JBTable jbTable = hToolWindowPageOne.getJbTable();
      DefaultTableModel model = (DefaultTableModel) jbTable.getModel();
      model.setRowCount(0);
      try {
        List<List<Object>> tableOneData = getTableOneData(project);
        for (List<Object> objects : tableOneData) {
          model.addRow(objects.toArray(new Object[0]));
        }
      } catch (Exception e) {
        ActionToolUtil.showNotification(project, NotificationType.ERROR, "刷新表格出错：" + e.getMessage());
      }
      jbTable.repaint();
    });

    // 字段表格刷新按钮执行操作
    refreshAction.initRefresh(2, () -> {
      WindowEntity windowEntity = windowEntityMap.get(project);
      HToolWindowPage hToolWindowPageOne = windowEntity.getHToolWindowPageOne();
      HToolWindowPage hToolWindowPageTwo = windowEntity.getHToolWindowPageTwo();
      JBTable jbTableOne = hToolWindowPageOne.getJbTable();
      JBTable jbTableTwo = hToolWindowPageTwo.getJbTable();
      DefaultTableModel jbTableTwoModel = (DefaultTableModel) jbTableTwo.getModel();
      jbTableTwoModel.setRowCount(0);
      try {
        Object value = getOneSetData(jbTableOne, hToolWindowPageOne);
        renderTableData(project, jbTableTwoModel, value);
      } catch (Exception e) {
        LOG.info(e.getMessage(), e);
        ActionToolUtil.showNotification(project, NotificationType.ERROR, "刷新表格出错：" + e.getMessage());
      }
    });
    return refreshAction;
  }

  /**
   * 创建JPanel 并设置每一步操作逻辑
   * @param project    项目对象
   * @param toolWindow 工具窗口对象
   * @return JPanel
   */
  private JPanel crateJPanel(Project project, ToolWindow toolWindow) {
    WindowEntity windowEntity = windowEntityMap.get(project);
    HToolWindowPage hToolWindowPageOne = windowEntity.getHToolWindowPageOne();
    HToolWindowPage hToolWindowPageTwo = windowEntity.getHToolWindowPageTwo();
    SwingViewWrapper swingViewWrapper = windowEntity.getSwingViewWrapper();
    AtomicInteger step = windowEntity.getStep();
    List<JPanel> jPanels = windowEntity.getJPanels();
    HToolWindowView hToolWindowView = new HToolWindowView(jPanels).next(1, () -> {
      JBTable jbTable = hToolWindowPageOne.getJbTable();
      JTextField filterText = hToolWindowPageOne.getFilterText();
      String text = filterText.getText();
      List<Vector<?>> tableChooseData = tableChooseData(jbTable);
      int size = tableChooseData.size();
      if (size == 0 && text.isEmpty()) {
        ActionToolUtil.showNotification(project, NotificationType.ERROR, ModuleInformation.TIP_WINDOW_TABLE);
        return false;
      }
      return true;
    }).next(2, () -> {
      JTextField filterText = hToolWindowPageOne.getFilterText();
      JBTable jbTableOne = hToolWindowPageOne.getJbTable();
      JBTable jbTableTwo = hToolWindowPageTwo.getJbTable();
      List<Vector<?>> tableChooseDataOne = tableChooseData(jbTableOne);
      Map<ModuleInputEnum, String> values = swingViewWrapper.getValues();
      String fieldHas = values.get(ModuleInputEnum.FIELD_HAS);
      int size = tableChooseDataOne.size();
      if (size > 1 && fieldHas.equals("选定字段")) {
        ActionToolUtil.showNotification(project, NotificationType.ERROR, ModuleInformation.TIP_WINDOW_HAS);
        return false;
      } else if (size > 1 || !fieldHas.equals("选定字段")) {
        crateFile(project);
        toolWindow.hide();
        return false;
      } else {
        // 只选择了一个表单并且字段信息为选定字段，需要展示该表单的字段信息提供用户选择生成对应的字段
        DefaultTableModel defaultTableModel = (DefaultTableModel) jbTableTwo.getModel();
        defaultTableModel.setRowCount(0);
        try {
          Object value;
          if (size == 0) {
            value = filterText.getText();
          } else {
            value = tableChooseDataOne.get(0).get(1);
          }
          renderTableData(project, defaultTableModel, value);
        } catch (Exception e) {
          LOG.info(e.getMessage(), e);
          ActionToolUtil.showNotification(project, NotificationType.ERROR, "刷新表格出错：" + e.getMessage());
        }
        return true;
      }
    }).next(3, () -> {
      JBTable jbTable = hToolWindowPageTwo.getJbTable();
      List<Vector<?>> tableChooseData = tableChooseData(jbTable);
      if (tableChooseData.isEmpty()) {
        ActionToolUtil.showNotification(project, NotificationType.ERROR, ModuleInformation.TIP_WINDOW_TABLE);
        return false;
      }
      crateFile(project);
      toolWindow.hide();
      return false;
    });
    return hToolWindowView.setup(step);
  }

  /**
   * 通过传递的表格获取选中的行数据
   * @param jbTable 表格
   * @return 选中的行数据
   */
  private static List<Vector<?>> tableChooseData(JBTable jbTable) {
    DefaultTableModel jbTableOneModel = (DefaultTableModel) jbTable.getModel();
    @SuppressWarnings("rawtypes") Vector<Vector> tableOneData = jbTableOneModel.getDataVector();
    List<Vector<?>> chooseList = new ArrayList<>();
    for (Vector<?> rowData : tableOneData) {
      boolean isChoose = (boolean) rowData.get(0);
      if (isChoose) {
        chooseList.add(rowData);
      }
    }
    return chooseList;
  }

  /**
   * 获取第一步中的表单值，如果第一步选择了表单数据则获取选中的行数据隐藏列中的ID，否则获取筛选框输入的值
   * @param jbTableOne         表单表格
   * @param hToolWindowPageOne 表单页面
   * @return 选中的表单ID或筛选框中的值
   */
  private static Object getOneSetData(JBTable jbTableOne, HToolWindowPage hToolWindowPageOne) {
    List<Vector<?>> oneIdList = tableChooseData(jbTableOne);
    int selectedRow = oneIdList.size();
    Object value;
    if (selectedRow == 0) {
      JTextField filterText = hToolWindowPageOne.getFilterText();
      value = filterText.getText();
    } else {
      value = oneIdList.get(0).get(1);
    }
    return value;
  }

  /**
   * 刷新数据表格字段信息
   * @param project 项目信息
   * @param model   表格model
   * @param value   要更新的数据
   */
  private void renderTableData(Project project, DefaultTableModel model, Object value) throws Exception {
    String string = String.valueOf(value);
    List<List<Object>> tableOneData;
    try {
      // 判断是不是第一个表单选择的表格信息
      Long formId = Long.valueOf(string);
      tableOneData = getTableTwoData(project, formId);
    } catch (Exception e) {
      tableOneData = new ArrayList<>();
      extracted(project, tableOneData, new JsonArray(), string, string);
    }
    for (List<Object> objects : tableOneData) {
      model.addRow(objects.toArray(new Object[0]));
    }
  }

  /**
   * 查询数据中存在的表格信息
   * @param project 项目信息
   * @return 表单信息解析过后的集合数据
   */
  private List<List<Object>> getTableOneData(Project project) throws Exception {
    List<FormDesign> query = SqlExecute.query(project, FormDesign.class, "SELECT ID,NAME,'CAP4' as formType FROM cap_form_definition;");
    List<List<Object>> list = new ArrayList<>();
    for (FormDesign formDesign : query) {
      String id = formDesign.getId();
      String name = formDesign.getName();
      String formType = formDesign.getFormType();
      list.add(List.of(new Object[]{false, id, name, formType}));
    }
    return list;
  }

  /**
   * 查询指定表单中的所有字段信息(包含明细表)
   * @param project 项目对象
   * @param formId  表单ID
   * @return 字段信息集合
   */
  private List<List<Object>> getTableTwoData(Project project, Long formId) throws Exception {
    List<FormDesign> query = SqlExecute.query(project, FormDesign.class, "SELECT ID,FIELD_INFO as fieldInfo FROM cap_form_definition where ID = " + formId + ";");
    List<List<Object>> list = new ArrayList<>();
    for (FormDesign formDesign : query) {
      String fileInfo = formDesign.getFieldInfo();
      JsonObject jsonObject = JsonParser.parseString(fileInfo).getAsJsonObject();
      JsonObject frontFormmain = jsonObject.getAsJsonObject("front_formmain");
      String displayMain = frontFormmain.get("display").getAsString();
      String tableNameMain = frontFormmain.get("tableName").getAsString();
      JsonArray fieldInfoMain = frontFormmain.get("fieldInfo").getAsJsonArray();
      JsonObject jsonObjectSort = new JsonObject();
      jsonObjectSort.addProperty("id", 345L);
      jsonObjectSort.addProperty("name", "sort");
      jsonObjectSort.addProperty("type", "扩展");
      jsonObjectSort.addProperty("display", "sort");
      fieldInfoMain.add(jsonObjectSort);
      extracted(project, list, fieldInfoMain, tableNameMain, displayMain);
      jsonObject.get("formsons").getAsJsonArray().forEach(jsonElement -> {
        try {
          JsonObject asJsonObject = jsonElement.getAsJsonObject();
          String displaySon = asJsonObject.get("display").getAsString();
          String tableNameSon = asJsonObject.get("tableName").getAsString();
          JsonArray fieldInfoSon = asJsonObject.get("fieldInfo").getAsJsonArray();
          // 添加明细表中关键的字段
          JsonObject jsonObjectID = new JsonObject();
          jsonObjectID.addProperty("id", 123L);
          jsonObjectID.addProperty("name", "id");
          jsonObjectID.addProperty("type", "扩展");
          jsonObjectID.addProperty("display", "id");
          JsonObject jsonObjectFormMan = new JsonObject();
          jsonObjectFormMan.addProperty("id", 234L);
          jsonObjectFormMan.addProperty("name", "formmain_id");
          jsonObjectFormMan.addProperty("type", "扩展");
          jsonObjectFormMan.addProperty("display", "formmain_id");
          Gson gson = new Gson();
          JsonObject[] array = gson.fromJson(fieldInfoSon, JsonObject[].class);
          List<JsonObject> listS = Arrays.asList(array);
          List<JsonObject> newListS = new ArrayList<>();
          newListS.add(jsonObjectID);
          newListS.add(jsonObjectFormMan);
          newListS.add(jsonObjectSort);
          newListS.addAll(listS);
          JsonArray jsonArray = gson.toJsonTree(newListS).getAsJsonArray();
          extracted(project, list, jsonArray, tableNameSon, displaySon);
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      });
    }
    return list;
  }

  private static void extracted(Project project, List<List<Object>> list, JsonArray fieldInfo, String tableName, String displayForm) throws Exception {
    SqlExec sqlExec = new SqlExec().mysql("DESCRIBE " + tableName + ";")
        // oracle查询数据库表字段信息要用表名称 区分大小写
        .oracle("SELECT column_name as field, data_type as type FROM all_tab_columns WHERE table_name = '" + tableName.toUpperCase() + "'")
        // sqlserver查询数据库表字段信息
        .sqlserver("SELECT COLUMN_NAME as field, DATA_TYPE as type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '" + tableName + "';");
    List<SqlEntity> queryMain = SqlExecute.query(project, SqlEntity.class, sqlExec);
    if (fieldInfo.isEmpty()) {
      queryMain.forEach(sqlEntity -> {
        String field = sqlEntity.getField();
        String type = sqlEntity.getType();
        list.add(List.of(new Object[]{false, 123L, field, "", "", type, "", tableName}));
      });
    } else {
      Map<String, JsonObject> fieldMap = new HashMap<>();
      fieldInfo.forEach(jsonElement -> {
        JsonObject asJsonObject = jsonElement.getAsJsonObject();
        String name = asJsonObject.get("name").getAsString().toLowerCase();// 表单设计中的字段
        fieldMap.put(name, asJsonObject);
      });
      queryMain.forEach(sqlEntity -> {
        String key = sqlEntity.getField().toLowerCase();
        String field = sqlEntity.getField();
        String fieldType = sqlEntity.getType();
        JsonObject jsonObject = fieldMap.get(key);
        // 处理老版本中表单设置排序可能叫groupsort的字段但数据库列名为sort
        if (jsonObject == null && field.equals("sort")) {
          jsonObject = fieldMap.get("groupsort");
        }
        if (jsonObject == null) {
          list.add(List.of(new Object[]{false, 123L, field, field, "扩展", fieldType, displayForm, tableName}));
        } else {
          long id = jsonObject.get("id").getAsLong();
          String type = jsonObject.get("type").getAsString();// 字段类型
          String display = jsonObject.get("display").getAsString();// 字段显示名字
          list.add(List.of(new Object[]{false, id, field, display, type, fieldType, displayForm, tableName}));
        }
      });
    }
  }


  /**
   * 根据项目创建文件。
   * 本方法首先会获取项目配置信息，之后根据配置信息和用户在界面中的选择，
   * 收集表单字段信息，并根据这些信息生成实体类文件。
   * @param project 代表当前项目的实体
   */
  private void crateFile(Project project) {
    try {
      // 获取项目配置实体
      ConfigEntity configEntity = ActionToolUtil.getInformation(project);
      if (configEntity == null) {
        // 如果未配置，提示用户并返回
        ActionToolUtil.noConfig(project);
        return;
      }
      WindowEntity windowEntity = windowEntityMap.get(project);
      HToolWindowPage hToolWindowPageOne = windowEntity.getHToolWindowPageOne();
      HToolWindowPage hToolWindowPageTwo = windowEntity.getHToolWindowPageTwo();
      SwingViewWrapper swingViewWrapper = windowEntity.getSwingViewWrapper();
      // 从配置对话框获取用户选择的字段信息
      Map<ModuleInputEnum, String> values = swingViewWrapper.getValues();
      // 解析用户选择的字段信息
      String fieldHas = values.get(ModuleInputEnum.FIELD_HAS);
      String fieldShift = values.get(ModuleInputEnum.FIELD_SHIFT);
      String fieldXml = values.get(ModuleInputEnum.FIELD_XML);
      // 处理多个表单选择的情况
      JBTable jbTableOne = hToolWindowPageOne.getJbTable();
      List<Vector<?>> tableChooseDataOne = tableChooseData(jbTableOne);
      int size = tableChooseDataOne.size();
      if (size >= 1 && !fieldHas.equals("选定字段")) { // 多个表创建 必不可能是选定字段
        for (Vector<?> objects : tableChooseDataOne) {
          // 获取每个选择的表单设计的ID和名称
          Object formDesignId = objects.get(1);
          Object formDesignName = objects.get(2);
          String valueOf = String.valueOf(formDesignName);
          // 获取并处理表单设计的字段信息
          List<List<Object>> tableTwoData = getTableTwoData(project, Long.valueOf(String.valueOf(formDesignId)));
          Map<String, List<Map<String, String>>> tableMap = new HashMap<>();
          for (List<Object> tableTwoDatum : tableTwoData) {
            Object field = tableTwoDatum.get(2);
            Object name = tableTwoDatum.get(3);
            Object fieldType = tableTwoDatum.get(5);
            Object tableShowName = tableTwoDatum.get(6);
            Object formName = tableTwoDatum.get(7);
            String fieldValueOf = String.valueOf(field);
            // 根据用户配置过滤字段
            if (fieldHas.equals("排除无关字段")) {
              String lowerCase = fieldValueOf.toLowerCase();
              String formNameStr = formName.toString();
              if (!formNameStr.contains("formson")) {
                if (!lowerCase.contains("field")
                    && !lowerCase.equals("id")
                    && !lowerCase.equals("start_date")// 创建时间
                    && !lowerCase.equals("modify_date")// 修改时间
                    && !lowerCase.equals("sort")) {
                  continue;
                }
              }
            }
            String endName;
            if (tableShowName != null) {
              if (tableShowName.equals("主表字段")) {
                endName = valueOf;
              } else {
                endName = valueOf + "_" + tableShowName;
              }
            } else {
              endName = valueOf;
            }
            // 处理并收集字段信息
            fieldEncamp(fieldShift, endName, tableMap, fieldType, formName, fieldValueOf, String.valueOf(name));
          }
          // 根据收集到的字段信息生成实体类
          cratePo(project, configEntity, tableMap, fieldXml);
        }
      } else if (size == 0 && !fieldHas.equals("选定字段")) {
        JTextField filterText = hToolWindowPageOne.getFilterText();
        // 去除符号 并且首字母大写
        String filterTextText = filterText.getText();
        String valueOf = FileUtil.upperFirstCase(SwingUi.removeSymbols(filterTextText));
        List<List<Object>> tableTwoData = new ArrayList<>();
        extracted(project, tableTwoData, new JsonArray(), filterTextText, filterTextText);
        Map<String, List<Map<String, String>>> tableMap = new HashMap<>();
        for (List<Object> tableTwoDatum : tableTwoData) {
          Object field = tableTwoDatum.get(2);
          Object name = tableTwoDatum.get(3);
          Object fieldType = tableTwoDatum.get(5);
          Object formName = tableTwoDatum.get(7);
          String fieldValueOf = String.valueOf(field);
          // 处理并收集字段信息
          fieldEncamp(fieldShift, valueOf, tableMap, fieldType, formName, fieldValueOf, String.valueOf(name));
        }
        // 根据收集到的字段信息生成实体类
        cratePo(project, configEntity, tableMap, fieldXml);
      } else {
        // 处理单个表单（可以是填写的表名，也可以是选择的表。选择的表优先级高于填写的表名）选择字段的情况
        String valueOf;
        if (size == 0) {
          JTextField filterText = hToolWindowPageOne.getFilterText();
          // 去除符号 并且首字母大写
          String filterTextText = filterText.getText();
          valueOf = FileUtil.upperFirstCase(SwingUi.removeSymbols(filterTextText));
        } else {
          Object formDesignName = tableChooseDataOne.get(0).get(2);
          valueOf = String.valueOf(formDesignName);
        }
        JBTable jbTableTwo = hToolWindowPageTwo.getJbTable();
        List<Vector<?>> tableChooseDataTwo = tableChooseData(jbTableTwo);
        Map<String, List<Map<String, String>>> tableMap = new HashMap<>();
        for (Vector<?> objects : tableChooseDataTwo) {
          // 收集单个表单的字段信息
          Object field = objects.get(2);
          Object name = objects.get(3);
          Object fieldType = objects.get(5);
          Object tableShowName = objects.get(6);
          Object formName = objects.get(7);
          String endName;
          if (tableShowName != null) {
            if (tableShowName.equals("主表字段")) {
              endName = valueOf;
            } else {
              endName = valueOf + "_" + tableShowName;
            }
          } else {
            endName = valueOf;
          }
          fieldEncamp(fieldShift, endName, tableMap, fieldType, formName, String.valueOf(field), String.valueOf(name));
        }
        // 根据收集到的字段信息生成实体类
        cratePo(project, configEntity, tableMap, fieldXml);
      }
      ActionToolUtil.showNotification(project, NotificationType.INFORMATION, "创建表单成功");
    } catch (Exception e) {
      // 异常处理逻辑（代码省略）
      LOG.info("创建表单出错：{}" + e.getMessage(), e);
      ActionToolUtil.showNotification(project, NotificationType.ERROR, "创建表单出错：" + e.getMessage());
    }
  }

  /**
   * 根据字段转换规则，更新表单字段信息。
   * @param fieldShift   字段转换规则，例如“字段名称转拼音”。
   * @param valueOf      表单字段的设计名称。
   * @param tableMap     存储表单字段信息的映射。
   * @param fieldType    字段类型。
   * @param formName     表单名称。
   * @param fieldValueOf 字段的值。
   * @param nameValueOf  需要转换的字段名称。
   */
  private void fieldEncamp(String fieldShift, String valueOf, Map<String, List<Map<String, String>>> tableMap, Object fieldType, Object formName, String fieldValueOf, String nameValueOf) {
    String fieldEndName;
    // 根据字段转换规则处理字段名称
    if (fieldShift.equals("字段名称转拼音")) {
      String lowerCase = nameValueOf.toLowerCase();
      String result = SwingUi.removeSymbols(lowerCase);
      fieldEndName = ActionToolUtil.convertToPinyin(result);
      // 若转换失败，则使用字段原始值
      if (fieldEndName == null || fieldEndName.isEmpty()) {
        fieldEndName = fieldValueOf;
      } else {
        fieldEndName = FileUtil.lowerFirstCase(fieldEndName);
      }
    } else {
      fieldEndName = fieldValueOf;
    }
    // 准备字段信息映射
    Map<String, String> mapItem = new HashMap<>();
    // 对应实体类属性的类型
    String fieldTypeContrast = fieldTypeContrast(String.valueOf(fieldType));
    String lowerCase = fieldValueOf.toLowerCase();
    if (lowerCase.equals("id") || lowerCase.equals("formmain_id")) {
      fieldTypeContrast = "java.lang.Long";
    }
    mapItem.put("type", fieldTypeContrast);
    // 对应实体类属性名称
    mapItem.put("field", fieldEndName);
    // 对应数据库字段名称
    mapItem.put("dataName", fieldValueOf);
    // 对应表单中显示名称
    mapItem.put("showName", nameValueOf);
    // 表的名称
    mapItem.put("formDesignName", valueOf);
    // 根据表单名称键，更新或添加字段信息到表单映射中
    String key = String.valueOf(formName);
    if (tableMap.containsKey(key)) {
      List<Map<String, String>> mapList = tableMap.get(key);
      mapList.add(mapItem);
    } else {
      List<Map<String, String>> objects = new ArrayList<>();
      objects.add(mapItem);
      tableMap.put(key, objects);
    }
  }

  /**
   * 创建PO实体类和hbm.xml文件
   * @param project      项目对象
   * @param configEntity 插件配置信息
   * @param tableMap     整理过后的实体类字段信息
   */
  private void cratePo(Project project, ConfigEntity configEntity, Map<String, List<Map<String, String>>> tableMap, String fieldXml) {
    Application application = ApplicationManager.getApplication();
    application.runWriteAction(() -> {
      try {
        PsiManager psiManager = PsiManager.getInstance(project);
        String basePath = project.getBasePath();
        if (basePath != null) {
          LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
          for (String string : tableMap.keySet()) {
            Set<String> setImport = new HashSet<>();
            StringBuilder stringBuilderName = new StringBuilder();
            StringBuilder stringBuilderField = new StringBuilder();
            AtomicReference<String> formDesignName = new AtomicReference<>();
            tableMap.get(string).forEach(map -> {
              String type = map.get("type");
              String field = map.get("field");
              String dataName = map.get("dataName");
              String showName = map.get("showName");
              if (!type.startsWith("java.lang")) {
                setImport.add("import " + type + ";");
              }
              String substring = type.substring(type.lastIndexOf(".") + 1);
              stringBuilderName.append("/***");
              if (!showName.isEmpty()) {
                stringBuilderName.append(showName).append(",");
              }
              stringBuilderName.append(dataName).append("***/").append("private ").append(substring).append(" ").append(field).append(";");
              String lowerCase = field.toLowerCase();
              if (lowerCase.equals("id")) {
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append("<id name=\"").append(field).append("\" type=\"").append(type).append("\" column=\"").append(dataName).append("\"><generator class=\"assigned\"/></id>");
                stringBuilderField.insert(0, stringBuilder);
              } else {
                stringBuilderField.append("<property name=\"").append(field).append("\" type=\"").append(type).append("\" column=\"").append(dataName).append("\"/>");
              }
              formDesignName.set(map.get("formDesignName"));
            });
            String formName = formDesignName.get();
            String sourcePath = configEntity.getSourcePath();
            String plugID = configEntity.getPluginID();
            if (sourcePath == null || sourcePath.isEmpty()) {
              sourcePath = "src_" + plugID;
            }
            Path path = Path.of(basePath, sourcePath);
            // 创建Java
            VirtualFile plugIDVir = localFileSystem.findFileByNioFile(path);
            VirtualFile virtualFileClass = FileUtil.createDirectories(this, plugIDVir, "com", "seeyon", "apps", plugID, "po");
            PsiDirectory classPsiDirectory = psiManager.findDirectory(virtualFileClass);
            String convertToPinyin = ActionToolUtil.convertToPinyin(formName);
            Map<ModuleInputEnum, String> values = new HashMap<>();
            values.put(ModuleInputEnum.CLASS_NANE, convertToPinyin);
            String join = String.join("", setImport);
            FileUtil.createClass(project, classPsiDirectory, values, "/java/po/Entity.java.sample", s -> s.replaceAll("\\$Import\\$", join).replaceAll("\\$FormName\\$", formName).replaceAll("\\$Filed\\$", stringBuilderName.toString()));
            if (classPsiDirectory != null) {
              classPsiDirectory.navigate(true);
            }
            if (fieldXml.equals("是")) {
              VirtualFile virtualFileMetaInf = FileUtil.createDirectories(this, virtualFileClass, "domain");
              PsiDirectory metaPsiDirectory = psiManager.findDirectory(virtualFileMetaInf);
              FileUtil.createXml(project, metaPsiDirectory, convertToPinyin + ".hbm", values, "/xml/po/Entity.hbm.xml.sample", s -> {
                String classAllName = values.get(ModuleInputEnum.CLASS_ALL_NAME);
                String packagePath = classAllName.substring(0, classAllName.lastIndexOf("."));
                return s.replaceAll("\\$FormName\\$", formName).replaceAll("\\$Package\\$", packagePath).replaceAll("\\$TableName\\$", string).replaceAll("\\$Property\\$", stringBuilderField.toString());
              }, true);
            }
          }
        }
      } catch (Exception e) {
        ActionToolUtil.showNotification(project, NotificationType.ERROR, "创建表单实体类出错：" + e.getMessage());
        LOG.info("创建表单实体类出错：" + e.getMessage(), e);
      }
    });
  }

  /**
   * 数据库字段类型对应java数据类型
   * @return 返回对应java类型的权限定义名称
   */
  private String fieldTypeContrast(String dataType) {
    String replaceAll = dataType.replaceAll("\\([^()]*\\)", "");
    String upperCase = replaceAll.toUpperCase();
    return switch (upperCase) {
      case "INT", "TINYINT", "INTEGER" -> {
        try {
          String pattern = ".*\\(([^()]*)\\).*";
          Pattern r = Pattern.compile(pattern);
          Matcher m = r.matcher(dataType);
          if (m.find()) {
            String group = m.group(1);
            String[] split = group.split(",");
            String value = split[0];
            int integer = Integer.parseInt(value);
            // 判断数字是否是LONG
            if (integer > 9) {
              yield "java.lang.Long";
            }
          }
        } catch (Exception e) {
          // 忽略
        }
        yield "java.lang.Integer";
      }
      case "DECIMAL" -> {
        try {
          String pattern = ".*\\(([^()]*)\\).*";
          Pattern r = Pattern.compile(pattern);
          Matcher m = r.matcher(dataType);
          if (m.find()) {
            String group = m.group(1);
            String[] split = group.split(",");
            if (split.length == 2) {
              String scaleStr = split[1].trim();
              int scale = Integer.parseInt(scaleStr);
              // scale == 0 表示没有小数位
              if (scale == 0) {
                yield "java.lang.Long";
              } else {
                yield "java.lang.Double";
              }
            }
          }
        } catch (Exception e) {
          // 忽略
        }
        yield "java.lang.Double"; // 默认是Double
      }
      case "SMALLINT" -> "java.lang.Short";
      case "BIGINT" -> "java.lang.Long";
      case "FLOAT" -> "java.lang.Float";
      case "DOUBLE", "DOUBLE PRECISION", "NUMBER", "NUMERIC" -> "java.lang.Double";
      case "DATE", "TIME", "DATETIME", "TIMESTAMP" -> "java.sql.Timestamp";
      case "BLOB", "LONGBLOB", "MEDIUMBLOB", "TINYBLOB", "RAW" -> "java.lang.Byte";
      case "BIT", "BOOLEAN" -> "java.lang.Boolean";
      default -> "java.lang.String";
    };
  }
}
